package com.alex.statistics.method.structureanalysis;

import com.alex.statistics.pojo.request.structureanalysis.StaticStructureRequest;
import com.alex.statistics.pojo.result.structureanalysis.StaticStructureResult;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class StaticStructureService {

    /**
     * 占比分析：计算各组成部分相对于整体的占比
     */
    public StaticStructureResult.ProportionResult calculateProportion(StaticStructureRequest.ProportionRequest request) {
        long startTime = System.currentTimeMillis();
        validateProportionRequest(request);

        // 计算整体总值（若未提供则自动求和）
        double total = request.getTotalValue() != null ? request.getTotalValue() :
                request.getComponentValues().stream().mapToDouble(Double::doubleValue).sum();

        // 计算各部分占比
        List<StaticStructureResult.ProportionResult.ProportionDetail> details = new ArrayList<>();
        for (int i = 0; i < request.getComponentNames().size(); i++) {
            String name = request.getComponentNames().get(i);
            double value = request.getComponentValues().get(i);
            double proportion = (value / total) * 100; // 转换为百分比
            details.add(new StaticStructureResult.ProportionResult.ProportionDetail(name, value, proportion));
        }

        // 构建结果
        StaticStructureResult.ProportionResult result = new StaticStructureResult.ProportionResult();
        result.setComputeTime(System.currentTimeMillis() - startTime);
        result.setTotalValue(total);
        result.setDetails(details);
        return result;
    }

    public StaticStructureResult.CompositionRatioResult calculateCompositionRatio(StaticStructureRequest.CompositionRatioRequest request) {
        long startTime = System.currentTimeMillis();
        validateCompositionRequest(request);

        // 1. 按分类名称进行分组汇总
        Map<String, Double> categorySumMap = new HashMap<>();
        for (int i = 0; i < request.getCategoryNames().size(); i++) {
            String categoryName = request.getCategoryNames().get(i);
            double value = request.getCategoryValues().get(i);

            // 累加同一分类的值
            categorySumMap.put(categoryName, categorySumMap.getOrDefault(categoryName, 0.0) + value);
        }

        // 2. 计算总合计值
        double total = categorySumMap.values().stream().mapToDouble(Double::doubleValue).sum();

        // 3. 计算各分类的构成比
        List<StaticStructureResult.CompositionRatioResult.CompositionDetail> details = new ArrayList<>();
        for (Map.Entry<String, Double> entry : categorySumMap.entrySet()) {
            String name = entry.getKey();
            double sumValue = entry.getValue();
            double ratio = (sumValue / total) * 100; // 转换为百分比
            details.add(new StaticStructureResult.CompositionRatioResult.CompositionDetail(name, sumValue, ratio));
        }

        // 4. 按占比降序排序，使结果更直观
        details.sort((d1, d2) -> Double.compare(d2.getRatio(), d1.getRatio()));

        // 5. 构建结果
        StaticStructureResult.CompositionRatioResult result = new StaticStructureResult.CompositionRatioResult();
        result.setComputeTime(System.currentTimeMillis() - startTime);
        result.setTotalValue(total);
        result.setDetails(details);
        return result;
    }
    /**
     * 帕累托分析：识别对结果影响最大的关键因素（二八定律）
     */
    public StaticStructureResult.ParetoResult calculatePareto(StaticStructureRequest.ParetoRequest request) {
        long startTime = System.currentTimeMillis();
        validateParetoRequest(request);

        // 计算总影响值
        double totalImpact = request.getImpactValues().stream().mapToDouble(Double::doubleValue).sum();

        // 合并因素名称和影响值，按影响值降序排序
        List<StaticStructureResult.ParetoResult.ParetoDetail> sortedDetails = new ArrayList<>();
        for (int i = 0; i < request.getFactorNames().size(); i++) {
            sortedDetails.add(new StaticStructureResult.ParetoResult.ParetoDetail(
                    request.getFactorNames().get(i),
                    request.getImpactValues().get(i),
                    0.0, // 占比先占位
                    0.0  // 累计占比先占位
            ));
        }
        // 按影响值降序排序
        sortedDetails.sort(Comparator.comparingDouble(StaticStructureResult.ParetoResult.ParetoDetail::getImpactValue).reversed());

        // 计算占比和累计占比
        double cumulative = 0.0;
        for (StaticStructureResult.ParetoResult.ParetoDetail detail : sortedDetails) {
            double proportion = (detail.getImpactValue() / totalImpact) * 100;
            cumulative += proportion;
            detail.setProportion(proportion);
            detail.setCumulativeProportion(cumulative);
        }

        // 识别关键因素（累计占比达到阈值的前N项）
        List<String> keyFactors = new ArrayList<>();
        double threshold = request.getThreshold();
        for (StaticStructureResult.ParetoResult.ParetoDetail detail : sortedDetails) {
            keyFactors.add(detail.getFactorName());
            if (detail.getCumulativeProportion() >= threshold) {
                break;
            }
        }

        // 构建结果
        StaticStructureResult.ParetoResult result = new StaticStructureResult.ParetoResult();
        result.setComputeTime(System.currentTimeMillis() - startTime);
        result.setTotalImpact(totalImpact);
        result.setThreshold(threshold);
        result.setSortedFactors(sortedDetails);
        result.setKeyFactors(keyFactors);
        return result;
    }

    // 参数校验：占比分析
    private void validateProportionRequest(StaticStructureRequest.ProportionRequest request) {
        if (request.getComponentNames() == null || request.getComponentNames().isEmpty()) {
            throw new IllegalArgumentException("组成部分名称不能为空");
        }
        if (request.getComponentValues() == null || request.getComponentValues().isEmpty()) {
            throw new IllegalArgumentException("组成部分数值不能为空");
        }
        if (request.getComponentNames().size() != request.getComponentValues().size()) {
            throw new IllegalArgumentException("组成部分名称与数值的数量必须一致");
        }
        if (request.getComponentValues().stream().anyMatch(v -> v < 0)) {
            throw new IllegalArgumentException("组成部分数值不能为负数");
        }
        if (request.getTotalValue() != null && request.getTotalValue() <= 0) {
            throw new IllegalArgumentException("整体总值必须大于0");
        }
    }

    // 参数校验：构成比分析
    private void validateCompositionRequest(StaticStructureRequest.CompositionRatioRequest request) {
        if (request.getCategoryNames() == null || request.getCategoryNames().isEmpty()) {
            throw new IllegalArgumentException("分类名称不能为空");
        }
        if (request.getCategoryValues() == null || request.getCategoryValues().isEmpty()) {
            throw new IllegalArgumentException("分类数值不能为空");
        }
        if (request.getCategoryNames().size() != request.getCategoryValues().size()) {
            throw new IllegalArgumentException("分类名称与数值的数量必须一致");
        }
        if (request.getCategoryValues().stream().anyMatch(v -> v < 0)) {
            throw new IllegalArgumentException("分类数值不能为负数");
        }
    }

    // 参数校验：帕累托分析
    private void validateParetoRequest(StaticStructureRequest.ParetoRequest request) {
        if (request.getFactorNames() == null || request.getFactorNames().isEmpty()) {
            throw new IllegalArgumentException("因素名称不能为空");
        }
        if (request.getImpactValues() == null || request.getImpactValues().isEmpty()) {
            throw new IllegalArgumentException("影响值不能为空");
        }
        if (request.getFactorNames().size() != request.getImpactValues().size()) {
            throw new IllegalArgumentException("因素名称与影响值的数量必须一致");
        }
        if (request.getImpactValues().stream().anyMatch(v -> v < 0)) {
            throw new IllegalArgumentException("影响值不能为负数");
        }
        if (request.getThreshold() <= 0 || request.getThreshold() > 100) {
            throw new IllegalArgumentException("阈值必须在(0, 100]范围内（百分比）");
        }
    }
}
    